package com.carrental.finance.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.carrental.finance.dto.RefundDTO;
import com.carrental.finance.entity.Payment;
import com.carrental.finance.entity.Refund;
import com.carrental.finance.mapper.PaymentMapper;
import com.carrental.finance.mapper.RefundMapper;
import com.carrental.finance.service.RefundService;
import com.carrental.finance.vo.RefundVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 退款服务实现类
 */
@Service
public class RefundServiceImpl extends ServiceImpl<RefundMapper, Refund> implements RefundService {

    @Autowired
    private PaymentMapper paymentMapper;

    /**
     * 创建退款记录
     *
     * @param refundDTO 退款DTO
     * @return 退款ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createRefund(RefundDTO refundDTO) {
        // 生成退款单号
        String refundNo = generateRefundNo();
        
        Refund refund = new Refund();
        BeanUtils.copyProperties(refundDTO, refund);
        refund.setRefundNo(refundNo);
        refund.setStatus(1); // 默认状态为待退款
        refund.setCreateTime(LocalDateTime.now());
        refund.setUpdateTime(LocalDateTime.now());
        
        // 保存退款记录
        save(refund);
        
        // 更新支付记录状态为已退款
        Payment payment = paymentMapper.selectById(refundDTO.getPaymentId());
        if (payment != null) {
            payment.setStatus(5); // 已退款
            payment.setUpdateTime(LocalDateTime.now());
            paymentMapper.updateById(payment);
        }
        
        return refund.getId();
    }

    /**
     * 根据ID获取退款详情
     *
     * @param id 退款ID
     * @return 退款VO
     */
    @Override
    public RefundVO getRefundById(Long id) {
        Refund refund = getById(id);
        if (refund == null) {
            return null;
        }
        
        return convertToVO(refund);
    }

    /**
     * 根据退款单号获取退款详情
     *
     * @param refundNo 退款单号
     * @return 退款VO
     */
    @Override
    public RefundVO getRefundByRefundNo(String refundNo) {
        LambdaQueryWrapper<Refund> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Refund::getRefundNo, refundNo);
        
        Refund refund = getOne(wrapper);
        if (refund == null) {
            return null;
        }
        
        return convertToVO(refund);
    }

    /**
     * 根据支付ID获取退款详情
     *
     * @param paymentId 支付ID
     * @return 退款VO
     */
    @Override
    public RefundVO getRefundByPaymentId(Long paymentId) {
        LambdaQueryWrapper<Refund> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Refund::getPaymentId, paymentId);
        
        Refund refund = getOne(wrapper);
        if (refund == null) {
            return null;
        }
        
        return convertToVO(refund);
    }

    /**
     * 根据订单ID分页查询退款记录
     *
     * @param orderId 订单ID
     * @param page    分页参数
     * @return 退款VO分页
     */
    @Override
    public Page<RefundVO> pageOrderRefunds(Long orderId, Page<Refund> page) {
        LambdaQueryWrapper<Refund> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Refund::getOrderId, orderId);
        wrapper.orderByDesc(Refund::getCreateTime);
        
        Page<Refund> refundPage = page(page, wrapper);
        
        return convertToVOPage(refundPage);
    }

    /**
     * 根据用户ID分页查询退款记录
     *
     * @param userId 用户ID
     * @param page   分页参数
     * @return 退款VO分页
     */
    @Override
    public Page<RefundVO> pageUserRefunds(Long userId, Page<Refund> page) {
        LambdaQueryWrapper<Refund> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Refund::getUserId, userId);
        wrapper.orderByDesc(Refund::getCreateTime);
        
        Page<Refund> refundPage = page(page, wrapper);
        
        return convertToVOPage(refundPage);
    }

    /**
     * 分页查询退款记录
     *
     * @param page       分页参数
     * @param refundNo   退款单号
     * @param paymentNo  支付单号
     * @param orderNo    订单号
     * @param userId     用户ID
     * @param refundType 退款类型
     * @param status     退款状态
     * @param startTime  开始时间
     * @param endTime    结束时间
     * @return 退款VO分页
     */
    @Override
    public Page<RefundVO> pageRefunds(Page<Refund> page, String refundNo, String paymentNo, String orderNo, Long userId, Integer refundType, Integer status, String startTime, String endTime) {
        LambdaQueryWrapper<Refund> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(refundNo), Refund::getRefundNo, refundNo);
        wrapper.like(StringUtils.isNotBlank(paymentNo), Refund::getPaymentNo, paymentNo);
        wrapper.like(StringUtils.isNotBlank(orderNo), Refund::getOrderNo, orderNo);
        wrapper.eq(userId != null, Refund::getUserId, userId);
        wrapper.eq(refundType != null, Refund::getRefundType, refundType);
        wrapper.eq(status != null, Refund::getStatus, status);
        
        if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime start = LocalDateTime.parse(startTime, formatter);
            LocalDateTime end = LocalDateTime.parse(endTime, formatter);
            wrapper.between(Refund::getCreateTime, start, end);
        }
        
        wrapper.orderByDesc(Refund::getCreateTime);
        
        Page<Refund> refundPage = page(page, wrapper);
        
        return convertToVOPage(refundPage);
    }

    /**
     * 处理退款回调
     *
     * @param refundNo      退款单号
     * @param transactionId 交易流水号
     * @param status        退款状态
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean handleRefundCallback(String refundNo, String transactionId, Integer status) {
        LambdaQueryWrapper<Refund> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Refund::getRefundNo, refundNo);
        
        Refund refund = getOne(wrapper);
        if (refund == null) {
            return false;
        }
        
        // 更新退款状态和交易流水号
        refund.setStatus(status);
        refund.setTransactionId(transactionId);
        if (status == 3) { // 退款成功
            refund.setRefundTime(LocalDateTime.now());
        }
        refund.setUpdateTime(LocalDateTime.now());
        
        return updateById(refund);
    }

    /**
     * 取消退款
     *
     * @param id 退款ID
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelRefund(Long id) {
        Refund refund = getById(id);
        if (refund == null) {
            return false;
        }
        
        // 只有待退款和退款中的订单可以取消
        if (refund.getStatus() != 1 && refund.getStatus() != 2) {
            return false;
        }
        
        // 更新退款状态为退款失败
        refund.setStatus(4);
        refund.setUpdateTime(LocalDateTime.now());
        
        boolean result = updateById(refund);
        
        // 恢复支付记录状态
        if (result) {
            Payment payment = paymentMapper.selectById(refund.getPaymentId());
            if (payment != null) {
                payment.setStatus(3); // 恢复为支付成功
                payment.setUpdateTime(LocalDateTime.now());
                paymentMapper.updateById(payment);
            }
        }
        
        return result;
    }

    /**
     * 生成退款单号
     */
    private String generateRefundNo() {
        // 生成格式为：R + 当前时间（年月日时分秒）+ 6位随机数
        String timeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String randomStr = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 6);
        return "R" + timeStr + randomStr;
    }

    /**
     * 转换退款实体为VO
     */
    private RefundVO convertToVO(Refund refund) {
        if (refund == null) {
            return null;
        }
        
        RefundVO vo = new RefundVO();
        BeanUtils.copyProperties(refund, vo);
        
        // 设置退款类型名称
        vo.setRefundTypeName(getRefundTypeName(refund.getRefundType()));
        
        // 设置退款状态名称
        vo.setStatusName(getStatusName(refund.getStatus()));
        
        // TODO: 调用用户服务获取用户信息
        
        return vo;
    }

    /**
     * 转换退款分页为VO分页
     */
    private Page<RefundVO> convertToVOPage(Page<Refund> page) {
        Page<RefundVO> voPage = new Page<>();
        voPage.setCurrent(page.getCurrent());
        voPage.setSize(page.getSize());
        voPage.setTotal(page.getTotal());
        
        List<RefundVO> voList = page.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
        
        voPage.setRecords(voList);
        return voPage;
    }

    /**
     * 获取退款类型名称
     */
    private String getRefundTypeName(Integer refundType) {
        if (refundType == null) {
            return "";
        }
        
        switch (refundType) {
            case 1:
                return "押金退款";
            case 2:
                return "租金退款";
            case 3:
                return "其他退款";
            default:
                return "未知类型";
        }
    }

    /**
     * 获取退款状态名称
     */
    private String getStatusName(Integer status) {
        if (status == null) {
            return "";
        }
        
        switch (status) {
            case 1:
                return "待退款";
            case 2:
                return "退款中";
            case 3:
                return "退款成功";
            case 4:
                return "退款失败";
            default:
                return "未知状态";
        }
    }
} 